<?php
/**
 * @category 	Validate.php
 * @author 		Sung Hoon, Cho (akdddnet@gmail.com)
 * @since		2008. 07. 31
 * @license		BSD License
 * @version		0.3
 * 
 * 수정사항
 * 	- 2010. 12. 30
 * 		1. 닷넷 영향을 받았던 코딩 체계를 자바 환경으로 수정함.
 * 
 * 	- 2011. 03. 03
 * 		1. 사용자 아이디 체크 함수 추가.
 */

	class Validate
	{
		private $str;
		private $ayType;
		
		
		private $required   	= '반드시 입력하셔야 하는 사항입니다.';
		private $match 			= '입력된 내용이 일치하지 않습니다.';
		private $min_value		= '##MIN## 이상의 값을 입력해주세요.';
		private $max_value		= '##MAX## 이하의 값을 입력해주세요.';
		private $min_byte		= '입력된 내용의 길이가 ##MIN## Byte 이상이어야 합니다.';
		private $max_byte		= '입력된 내용의 길이가 ##MAX## Byte 이하이어야 합니다.';
		
		private $userid			= '4~12자의 영문 소문자와 숫자, 특수기호(_)만 사용할 수 있습니다.';
		private $email			= '이메일 형식이 올바르지 않습니다.';
		private $hangul			= '반드시 한글로 입력하셔야 합니다.';
		private $number			= '숫자만 입력하셔야 합니다.';
		private $eng			= '영문으로만 입력하셔야 합니다.';
		private $ssn			= '주민등록번호 형식이 올바르지 않습니다.';
		private $foreignerno	= '외국인 등록번호 형식이 올바르지 않습니다.';
		private $phone			= '핸드폰 번호 형식이 올바르지 않습니다.';
		private $tell			= '전화번호 형식이 올바르지 않습니다.';
		private $zip			= '우편번호 형식이 올바르지 않습니다.';
		private $bizno			= '사업자 등록번호 형식이 올바르지 않습니다.';
		private $user			= '입력하신 내용이 올바르지 않습니다.';
		private $password		= '비밀번호는 최소 6자리 숫자, 알파벳 혼합으로 입력하셔야 합니다.';
		
	
		function __construct()
		{
			// 초기화
			$this->str = '';
			$this->ayType = array(	 'required'
									,'userid'
									,'hangul'
									,'match'
									,'number'
									,'email'
									,'phone'
									,'tell'
									,'zip'
									,'ssn'
									,'foreignerno'
									,'bizno'
									,'min_value'
									,'max_value'
									,'min_byte'
									,'max_byte'
									,'user'		/*  사용자 정의 패턴 검사 (사용자 아이디 검사 아님) */
									,'password'
								);
		}
		
		
		/**
		 * validate할 항목을 추가합니다.
		 * 
		 * @param string $key : 검사 type
		  						required
		  						userid
		       					hangul
		  						match
		  						number
		  						email
		  						phone
		  						tell
		  						zip
		  						ssn
		  						foreignerno
		  						bizno
		  						min_value
		  						max_value
		  						min_byte
		  						max_byte
		  						user
		  						password
		 * @param string $value : 검사할 값
		 * @param string $pn : title
		 * 
		 * @return void
		 */
		public function add($key, $value, $pn)
		{
			// 배열일 경우
			if(is_array($key))
			{
				// 배열 형태 맞춤 (2중 for를 돌리지 않기위해서 ㅠ) 
				// 차후에 좋은 방법이 있으면 수정 해주시기 바랍니다. ㅠ
				$tmp_array = null;
				foreach($key as $type=>$tvalue)
				{
					if(is_numeric($type))
						$tmp_array[$tvalue] = $tvalue;
					else 
						$tmp_array[$type] = $tvalue;
				}
				
				foreach($tmp_array as $type=>$tvalue)
				{
					if(array_search($type, $this->ayType) >= 0)
					{
						// key하고 value값이 같으면  기본셋팅으로 가고;;
						if(!strcmp($type, $tvalue))
							$this->_switch($type, $pn, $value);
						else 
							$this->_switch($type, $pn, $value, $tvalue);
					}
				}
			}
			else 
			{
				if(array_search($key, $this->ayType) >= 0)
				{
					$this->_switch($key, $pn, $value);
				}	
			}

			
		}
		
		
		/**
		 * type에따라 필요한 함수 호출
		 * 
		 * @param string $type : 검사할 타입
		 * @param string $txt : title
		 * @param string $value1 : 검사할 값
		 * @param string $value2 : 범위
		 * 
		 * @return void;
		 */
		protected function _switch($type, $txt, $value1, $value2='')
		{
			switch($type)
			{ 
				case 'required' :
				case 'userid' :
				case 'password' :
				case 'hangul' :
				case 'number' :
				case 'email' :
				case 'phone' :
				case 'tell' :
				case 'zip' :
				case 'ssn' :
				case 'foreignerno' :
				case 'bizno' :
					$this->str .= $this->$type($txt, $value1);
					break;
				case 'match' :
					$this->str .= $this->match($txt, $value1, $value2);
					break;
				case 'user' :
				case 'min_value' :
				case 'max_value' :
				case 'min_byte' :
				case 'max_byte' :
					$this->str .= $this->extent($type, $txt, $value1, $value2);
					break;
			}
		}
		
		/**
		 * 전달받은 문자열을 지정한 범위만큼 검사합니다.
		 * 
		 * @param string $type : 검사할 타입
		 * @param string $pn : 출력이름
		 * @param string $value : 검사할 문자열
		 * @param int $value2 : 범위
		 * 
		 * @return void;
		 */
		public function extent($type, $pn, $value, $value2)
		{
			if(!strcmp($type, 'min_value'))
			{
				if($value < $value2)
					$this->str .= '['.$pn.'] '.str_replace('##MIN##', $value2, $this->min_value).'\\r\\n';
			}
			else if(!strcmp($type, 'max_value')) 
			{
				if($value > $value2)
					$this->str .= '['.$pn.'] '.str_replace('##MAX##', $value2, $this->max_value).'\\r\\n';
			}
			else if(!strcmp($type, 'min_byte'))
			{
				$byte = Common::getByte($value);
				
				if($byte < $value2)
					$this->str .= '['.$pn.'] '.str_replace('##MIN##', $value2, $this->min_byte).'\\r\\n';
			}
			else if(!strcmp($type, 'max_byte')) 
			{
				$byte = Common::getByte($value);
				if($byte > $value2)
					$this->str .= '['.$pn.'] '.str_replace('##MAX##', $value2, $this->max_byte).'\\r\\n';
			}
			// 테스트 안해봄
			else  if(!strcmp($type, 'user'))
			{
				if(!Common::isNullOrEmpty($value))
				{
					if(!preg_match($value2, $value))
						$this->str .= '['.$pn.'] '.$this->user.'\\r\\n';
				}
			}
			
		}
		
		/**
		 * 반드시 입력해야되는 사항
		 * 
		 * @param {string} $pn : title
		 * @param {string} $value : 값
		 * @return void;
		 */
		public function required($pn, $value)
		{
			// 빈값이면
			if(Common::isNullOrEmpty($value))
				$this->str .= '['.$pn.'] '.$this->required.'\\r\\n';
		}
		
		/**
		 * 전달받은 2개의 값이 일치하는지 확인합니다. 
		 * 
		 * @param string $pn : title
		 * @param string $value1 : 문자열
		 * @param string $value2 : 비교할 문자열
		 * @return void;
		 */
		public function match($pn, $value1, $value2)
		{
			if(strcmp($value1, $value2))
				$this->str .= '['.$pn.'] '.$this->match.'\\r\\n';
		}
		
		
		/**
		 * 입력받은 값이 한글인지 확인
		 * 
		 * @param string $pn
		 * @param string $value
		 * @return void;
		 */
		public function hangul($pn, $value)
		{
			if(!Common::isNullOrEmpty($value))
			{
				if(!preg_match('/^[가-힣]+$/', $value))
					$this->str .= '['.$pn.'] '.$this->hangul.'\\r\\n';
			}
		}
		
		
		/**
		 * 사용자 아이디 체크 (4~12자 숫자, 영문, _ 만 허용) 
		 * 
		 * @param string $pn
		 * @param string $value
		 */
		public function userid($pn, $value) {
			if(!Common::isNullOrEmpty($value)) {
				if(!preg_match(' /^[a-z0-9_]{4,12}$/', $value))
					$this->str .= '['.$pn.'] '.$this->userid.'\\r\\n';
			}
		}
		
		
		/**
		 * 비밀번호 검사 (최소 6자리 숫자, 알파벳 혼합)
		 * 
		 * @param string $pn
		 * @param string $value
		 */
		public function password($pn, $value) {
			//value.length >= 6 && /\d/.test(value) && /[a-z]/i.test(value)
			if(!Common::isNullOrEmpty($value)) {
				if(strlen($value) < 6 && !preg_match('/\d/', $value) && !preg_match('/[a-z]/', $value)) {
					$this->str .= '['.$pn.'] '.$this->password.'\\r\\n';
				}
			}
		}
		
		
		/**
		 * 입력받은 값이 숫자인지 확인
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function number($pn, $value)
		{
			if(!Common::isNullOrEmpty($value))
			{
				// 소수점 포함
				// 2008.10.24 by akddd
				if(!preg_match('/^[0-9\.]+$/', $value))
					$this->str .= '['.$pn.'] '.$this->number.'\\r\\n';
			}
		}
		
		/**
		 * 입력받은 값이 영문인지 확인
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function eng($pn, $value)
		{
			if(!Common::isNullOrEmpty($value))
			{
				if(!preg_match('/^[a-zA-Z]+$/', $value))
					$this->str .= '['.$pn.'] '.$this->eng.'\\r\\n';
			}
		}
		
		/**
		 * 주민등록 번호 체크
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function ssn($pn, $value)
		{
			$bl = false;
			if(!Common::isNullOrEmpty($value))
			{
			 	// 숫자면 가져오기
				$value = str_replace('-', '', $value);
			 	$value = preg_replace('/^[0-9]$/', '', $value);
			 	
				if(preg_match('/^(\d{6})(\d{7})$/', $value))
				{
					// 주민등록번호 체크
					$buf = array();
					
					for($i=0;$i<13;$i++) 
						$buf[$i]= $value[$i];
						
					$num=array(2,3,4,5,6,7,8,9,2,3,4,5);
					for($i=$sum=0;$i<12;$i++) 
						$sum+=($buf[$i]*=$num[$i]);
					
					if((11-($sum%11))%10!=$buf[12])
						$bl = false; 
					else 
						$bl = true;
				}
				else 
					$bl = false;
				
				if(!$bl)
					$this->str .= '['.$pn.'] '.$this->ssn.'\\r\\n';
			 }
		}
		
		/**
		 * 사업장 번호 체크
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function bizno($pn, $value)
		{
			$bl = false;
			if(!Common::isNullOrEmpty($value))
			{
				$value = str_replace('-', '', $value);
			 	$value = preg_replace('/^[0-9]$/', '', $value);
			 	
			 	
			 	$weight = '137137135'; // 자리수 weight 지정 
				$len = strlen($value); 
				$sum = 0; 
				$result = 0;
				
				// 사업장 번호가 10자리 체크
				if ($len <> 10) $bl=false; 
				
				for ($i = 0; $i < 9; $i++) 
					$sum = $sum + (substr($value,$i,1)*substr($weight,$i,1)); 
				
				$sum += ((substr($value,8,1)*5)/10); 
				$rst = $sum % 10; 
				
				if ($rst != 0)  
					$result = 10 - $rst; 
				
				$saub = substr($value,9,1); 
				
				if ($result <> $saub) $bl=false; 
				else $bl = true;


				if(!$bl)
					$this->str .= '['.$pn.'] '.$this->bizno.'\\r\\n';
			}
		}
		
		
		/**
		 * 외국인 등록 번호 (테스트 필요)
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function foreignerno($pn, $value)
		{
			$bl = false;
			if(!Common::isNullOrEmpty($value))
			{
			 	// 숫자면 가져오기
				$value = str_replace('-', '', $value);
			 	$value = preg_replace('/^[0-9]$/', '', $value);
			 	
				if(preg_match('/^(\d{6})(\d{5}[7-9]\d{1})$/', $value))
				{
					// 외국인 주민등록번호 체크
					$buf = array();
					
					for($i=0;$i<13;$i++) 
						$buf[$i]= $value[$i];
						
					$chk = $buf[7]*10 + $buf[8];
					
					if($chk %2 != 0) $bl = false;
					if (($buf[11] != 6)&&($buf[11] != 7)&&($buf[11] != 8)&&($buf[11] != 9)) $bl = false;
						
					$num=array(2,3,4,5,6,7,8,9,2,3,4,5);
					for($i=$sum=0;$i<12;$i++) 
						$sum+=($buf[$i]*=$num[$i]);
					
					if((11-($sum%11)+2)%10 != $buf[12])
						$bl = false; 
					else 
						$bl = true;
				}
				else 
					$bl = false;
				
				if(!$bl)
					$this->str .= '['.$pn.'] '.$this->foreignerno.'\\r\\n';
			 }
		}
		
		/**
		 * 이메일 체크
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function email($pn, $value)
		{
			if(!Common::isNullOrEmpty($value))
			{
				if(!preg_match('/^[_a-zA-Z0-9-\.]+@[\.a-zA-Z0-9-]+\.[a-zA-Z]+$/', $value))
					$this->str .= '['.$pn.'] '.$this->email.'\\r\\n';
			}
		}
		
		/**
		 * 핸드폰 체크
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function phone($pn, $value)
		{
			if(!Common::isNullOrEmpty($value))
			{
				if(!preg_match('/^(01[01346-9])-?([1-9]{1}[0-9]{2,3})-?([0-9]{4})$/'))
					$this->str .= '['.$pn.'] '.$this->phone.'\\r\\n';
			}
		}
		
		/**
		 * 전화번호 체크
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function tell($pn, $value)
		{
			if(!Common::isNullOrEmpty($value))
			{
				if(!preg_match('/^(0[2-8][0-5]?)-?([1-9]{1}[0-9]{2,3})-?([0-9]{4})$/'))
					$this->str .= '['.$pn.'] '.$this->phone.'\\r\\n';
			}
		}
		
		/**
		 * 우편번호 체크
		 * 
		 * @param string $pn 
		 * @param string $value
		 * @return void;
		 */
		public function zip($pn, $value)
		{
			if(!Common::isNullOrEmpty($value))
			{
				if(!preg_match('/^[0-9]{3}\-?[0-9]{3}$/'))
					$this->str .= '['.$pn.'] '.$this->zip.'\\r\\n';
			}
		}
		
		
		/**
		 * Validate
		 * 
		 * @return boolean 
		 */
		public function validate()
		{
			if(!Common::isNullOrEmpty($this->str))
				return false;
				
			return true;
		}
		
		/**
		 * ErrorMessage Return 
		 * 
		 * @return string $this->str
		 */
		public function getErrorMessage()
		{
			return $this->str;	
		}
	}
?>
